#pragma once

#ifndef _CNPC_H_
#define _CNPC_H_

#include "CBaseEntity.h"
#include "structs.h"
#include "CChar.h"
#include "CEnmityObject.h"
#include "CMobHandler.h"
#include <list>

#define AGGRO_HEARING		0x80
#define AGGRO_LOWHP			0x40
#define AGGRO_JOBABILITY	0x20
#define AGGRO_MAGIC			0x10
#define AGGRO_SIGHT			0x08
#define AGGRO_SCENT			0x04
#define AGGRO_WEAPONSKILL	0x02
#define AGGRO_TRUESIGHT		0x01

#define MOBTYPE_NORMAL		0x01
#define MOBTYPE_NOTORIOUS	0x02
#define MOBTYPE_FISHED		0x04
#define MOBTYPE_CALLED		0x08 //Called by Mob = Pets, Assistants, Mines
#define MOBTYPE_BATTLEFIELD	0x10
#define MOBTYPE_EVENT		0x20 //Special Event = Besieged, Campaign, E.Force, or Garrison




template<class T,class D>class T2List;

class CNpc : public CBaseEntity
{
public:

	unsigned char type;

	struct mobIDPoolEntry* m_pIdPoolEntry;
	unsigned char m_namePrefix;
	unsigned char namevis;

	struct position old_p;
	struct position targ_p;

	SpawnPoint * m_pSP;

	int			m_dropList;

	struct healthMob h;
	int			look;
	int			flag;
	char		lookc[20];

	short		sizeMod;

	unsigned	status;

	int			unknown;

	int			ownerId;

	bool		update;
	
	//If set to true, NPC will send update packets to anyone in the zone
	bool		alwaysZoneUpdate;

	int			currTarg;
	
	int			timestamp;
	CChar		*victim;

	int			m_timeOfKill;

	CBaseEntity * m_pLastDD;

	familyRanks m_statRank;

	unsigned short m_familyId;

	unsigned long tod;

	unsigned long long oldtime;
	unsigned long long updatetime;

	unsigned long long m_spawnTime;
	unsigned long long m_respawnTime;

	unsigned short m_mobType;

	bool m_isRoaming;
	unsigned long long m_goalReachedTime;

	bool m_isNm;
	bool m_isAgressive;

	bool m_isPet;
	bool isPet();
	void isPet(bool pet);

	unsigned int m_behaviour;

	unsigned int m_defaultDelay;

	void aggroChar(CChar * pChar);

	bool m_isCharSpawned;
	bool isCharSpawned();
	void isCharSpawned(bool charSpawned);

	//Total Enmity, key is based on enmity
	T2List<float,CEnmityObject*>* enmityList;
	//Deletes the players off of potential aggro list
	void clearEnmityList(void);

	// VE CE based Enmity, key is based on player ID
	T2List<unsigned int,enmityVC*>* enmityVCList;
	//Resets actual enmity
	void clearEnmityVCList(void);

	//std::vector<CEnmityObject*> enmityList;

	int	spawnId;
	unsigned short atNode;
	unsigned short walkNumNodes;
	int roamTime;
	// 0 = idle, 1 = walk, 2 = run
	unsigned short moveState;

	CNpc(void);
	~CNpc(void);

	void takePhysicalDamage(int damage, CBaseEntity * pDamageDealer);

	// returns true if a change happend
	int face(struct position p);
	// returns true if a change happend
	int moveTo(struct position p);

	void openDoor();
	void closeDoor();

	
	unsigned short getTargId();
	void setTargId(unsigned int targid);
	int updateNpc(unsigned char * data);

	void sendUpdate();
	void sendUpdateZone();
	void disengage();
	void engage(CBaseEntity *target);
	void die();
	//void roam(spawnpoint * spawnPoint);
	void checkAction();
	void inBattle();

	int getRealBaseExp(int charLevel);
	int getCappedBaseExp(int charLevel);

	void getDrops(CChar * schar);
	void setName(char * name);


	void setEnmity(CBaseEntity * entity, float enmity, bool addNew);
	void removeEnmity(CBaseEntity * entity);
	CBaseEntity* getHighestEnmity();

	// VE CE Enmity concepts are implementations of the research from http://kanican.livejournal.com/
	void decayVEnmity(float decayAmount);
	void updateVCEnmity(CBaseEntity * entity, int vEnmity, int cEnmity);
	void setLookVal(int look);

	int CNpc::getFStr(CBaseEntity * target);

	void attackAction();
	
	unsigned short getBaseToRank(short rank, short lvl);
	void calcStats();

	unsigned short getBaseEva();
	unsigned short getBaseDef();
	unsigned short getBaseAttack();
	unsigned short getBaseAccuracy(CBaseEntity * target);

	unsigned short getWeaponDamage();

	bool hasBehaviour(unsigned int behaviour);

	void getResist();

};

DWORD WINAPI Despawn(LPVOID lpParam);
DWORD WINAPI DespawnNoWait(LPVOID lpParam);


#endif
